package net.apps123.soundmeter;

import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import net.apps123.commonaclasses.MyBaseClass;
import net.apps123.commonaclasses.MyEditText;
import net.apps123.commonaclasses.MyEditText.MyEditTextListener;
import net.apps123.commonaclasses.SpectrumView;
import net.apps123.commonaclasses.Xaxis;
import net.apps123.commonaclasses.Xaxis.XaxisType;
import net.apps123.commonaclasses.Yaxis;
import net.apps123.interfaces.ILANCom;
import net.apps123.interfaces.ISoundCard;
import net.apps123.utils.IpUtils;

import org.eclipse.paho.client.mqttv3.MqttException;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue;

import jh.slm.calculations.Machine;
import jh.slm.calculations.RMSDetector.Averaging;

//import jh.slm.commonclasses.Machine;
//import jh.slm.commonclasses.Simulator;

// Cegis
public class MyClassHunXiang extends MyBaseClass {

    private static String ipStr;
    //机器
    Machine machine;
    private ArrayBlockingQueue<short[]> queue;
    //
    File setupFile;
    //fft平均值
    int nFftAverages = 20;
    //校准值
    double sysGain = 0.0;
    //机器线程
    Thread machineThread;
    //连接线程
    Thread connectThread;

    static private MyClassHunXiang instance = null;

    private Activity activity;

    private static byte[]  IpBytes = new byte[4];


    static public MyClassHunXiang Instance(HunXiangActivity activity) {
        if (instance == null) {
            instance = new MyClassHunXiang();
            instance.activity = activity;
            instance.InitViews(activity);

            String ipStr = IpUtils.getWifiIPAddress(activity);
            Log.d("====", "ipStr==" + ipStr);
            InetAddress ip = null;
            try {
                ip = InetAddress.getByName(ipStr);
                IpBytes = ip.getAddress();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }

        }
        return instance;
    }

    @Override
    protected void Startup() {
        fastSlowTv.setText(activity.getString(R.string.las));
        //=================读取配置信息==============================================
        File setupDir = activity.getFilesDir();
        setupFile = new File(setupDir, "Setup.dat");
        if (!setupFile.exists()) {
            try {
                setupFile.createNewFile();
                FileOutputStream stream = new FileOutputStream(setupFile);
                DataOutputStream writer = new DataOutputStream(stream);
                writer.writeInt(nFftAverages);
                writer.writeDouble(sysGain);
                writer.writeFloat(yAxis3.lowLevel);
                writer.writeFloat(yAxis3.range);
                writer.writeFloat(yAxis1.lowLevel);
                writer.writeFloat(yAxis1.range);
                writer.writeFloat(yAxisFft.lowLevel);
                writer.writeFloat(yAxisFft.range);
                stream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            FileInputStream stream = new FileInputStream(setupFile);
            DataInputStream reader = new DataInputStream(stream);
            nFftAverages = reader.readInt();
            sysGain = reader.readDouble();
            float l = reader.readFloat();
            float r = reader.readFloat();
            float h = l + r;
            int t = Math.round(r / 10 + 1);
            yAxis3.highLevel = h;
            yAxis3.nTics = t;
            yAxis3.invalidate();
            spectrumView3.ScalingHappened((int) l * 100, (int) r * 100);
            l = reader.readFloat();
            r = reader.readFloat();
            h = l + r;
            t = Math.round(r / 10 + 1);
            yAxis1.highLevel = h;
            yAxis1.nTics = t;
            yAxis1.invalidate();
            spectrumView1.ScalingHappened((int) l * 100, (int) r * 100);
            l = reader.readFloat();
            r = reader.readFloat();
            h = l + r;
            t = Math.round(r / 10 + 1);
            yAxisFft.highLevel = h;
            yAxisFft.nTics = t;
            yAxisFft.invalidate();
            fftSpectrumView.ScalingHappened((int) l * 100, (int) r * 100);
            stream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.Startup();

        //采集频率 48000 ，一次读取200， 一次计算长度9600
        int fs = 48000;
        int recordLength = 200;
//        int length = 600;
        int length = fs * recordLength / 1000;

        ILANCom lanCom = new LANCom();
        queue = lanCom.GetQueue();

        ISoundCard soundCard = new SoundCard(fs, length);

        fftAveraging.setText(String.valueOf(nFftAverages));
        systemGain.setText(String.valueOf(sysGain));
        machine = new Machine(lanCom, soundCard, fs, recordLength, length, nFftAverages, sysGain);

        //开始计算线程
        machineThread = new Thread(machine);
        machineThread.setName("machine");
        machineThread.start();

        while (!machine.running) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        //开启网线连接线程
        running = true;
        connectThread = new Thread(new Connect());
        connectThread.setName("connectThread");
        connectThread.start();

        //开始定时
        StartTimer();

    }

    @Override
    protected void Shutdown() {
        File setupDir = activity.getFilesDir();
        setupFile = new File(setupDir, "Setup.dat");
        try {
            FileOutputStream stream = new FileOutputStream(setupFile);
            DataOutputStream writer = new DataOutputStream(stream);
            writer.writeInt(nFftAverages);
            writer.writeDouble(sysGain);
            writer.writeFloat(yAxis3.lowLevel);
            writer.writeFloat(yAxis3.range);
            writer.writeFloat(yAxis1.lowLevel);
            writer.writeFloat(yAxis1.range);
            writer.writeFloat(yAxisFft.lowLevel);
            writer.writeFloat(yAxisFft.range);
            stream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            running = false;
            connectThread.join();
            machine.running = false;
            machineThread.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        super.Shutdown();

    }

    @Override
    protected void Reset() {
        if (machine == null)
            return;
        machine.Reset();
    }

    @Override
    protected void Pause() {
        if (machine == null)
            return;

        machine.Pause();
    }

    //设置了参数，重置数据
    public class Keyboard_Listener implements MyEditTextListener {
        @Override
        public void onKey(final MyEditText sender, String event) {
            if (machine == null)
                return;
            try {
                if (sender == fftAveraging) {
                    nFftAverages = Integer.parseInt(event);
                    machine.SetFftAveraging(nFftAverages);
                } else if (sender == systemGain) {
                    sysGain = Double.parseDouble(event);
                    machine.SetSystemGain(sysGain);
                    onReset();
                }
                machine.Reset();
            } catch (Exception e) {

            }
        }
    }

    @Override
    public FastSlow onFastSlow(FastSlow fs) {
        if (machine == null)
            return fs;

        switch (fs) {
            case Fast:
                machine.SetRmsAveraging(Averaging.Slow);
//                fastSlowTv.setText("快档");
                fastOrSlowBtn.setText("慢档");
                return FastSlow.Slow;
            case Slow:
                machine.SetRmsAveraging(Averaging.Fast);
                fastOrSlowBtn.setText("快档");
//                fastSlowTv.setText("慢档");
                return FastSlow.Fast;
        }

        return FastSlow.Fast;
    }

    @Override
    public void onPause() {
        super.onPause();
        if (functionBlock.getPause()) {
            pauseOrContBtn.setText("继续");
            functionBlock.setPause(true);
        } else {
            pauseOrContBtn.setText("暂停");
            functionBlock.setPause(false);
        }
    }

    public MLN onMLN(MLN mln) {
        switch (mln) {
            case Max:
                textView31.setText("LAN1");
                return MLN.Ln1;
            case Ln1:
                textView31.setText("LAN50");
                return MLN.Ln2;
            case Ln2:
                textView31.setText("LAN99");
                return MLN.Ln3;
            case Ln3:
                textView31.setText("LAMax");
                return MLN.Max;
        }

        return MLN.Max;
    }


    public void InitViews(HunXiangActivity activity) {

        this.activity = activity;

        fastOrSlowBtn = (Button) activity.findViewById(R.id.fastOrSlowBtn);
        pauseOrContBtn = (Button) activity.findViewById(R.id.pauseOrContBtn);

        fastSlowTv = (TextView) activity.findViewById(R.id.textView11);
        textView31 = (TextView) activity.findViewById(R.id.textView31);
        textView12 = (TextView) activity.findViewById(R.id.rmsValue);
        textView22 = (TextView) activity.findViewById(R.id.LAeqValueTv);
        textView32 = (TextView) activity.findViewById(R.id.LAMaxTV);
        textView42 = (TextView) activity.findViewById(R.id.peekTv);
        textView5 = (TextView) activity.findViewById(R.id.selectFreqTv);
        textView6 = (TextView) activity.findViewById(R.id.selectValueTv);

        button1 = (Button) activity.findViewById(R.id.startBtn);
        button2 = (Button) activity.findViewById(R.id.freqBtn);

        yAxis3 = (Yaxis) activity.findViewById(R.id.view01);
        yAxis1 = (Yaxis) activity.findViewById(R.id.view02);
        yAxisFft = (Yaxis) activity.findViewById(R.id.view03);

        yAxis1.setVisibility(View.INVISIBLE);
        yAxisFft.setVisibility(View.INVISIBLE);

        yAxis3.Init(2000, 8000);
        yAxis1.Init(2000, 8000);
        yAxisFft.Init(1000, 8000);

        xAxis3 = (Xaxis) activity.findViewById(R.id.view11);
        xAxis1 = (Xaxis) activity.findViewById(R.id.view12);
        xAxisFft = (Xaxis) activity.findViewById(R.id.view13);

        xAxis1.setVisibility(View.INVISIBLE);
        xAxisFft.setVisibility(View.INVISIBLE);

        xAxis3.Init(XaxisType.Cpb, 2000, 6000);
        xAxis1.Init(XaxisType.Cpb, 2000, 6000);
        xAxisFft.Init(XaxisType.Lin, 1000, 6000);

        spectrumView3 = (SpectrumView) activity.findViewById(R.id.view1);
        spectrumView1 = (SpectrumView) activity.findViewById(R.id.view2);
        fftSpectrumView = (SpectrumView) activity.findViewById(R.id.view3);

        spectrumView1.setVisibility(View.INVISIBLE);
        fftSpectrumView.setVisibility(View.INVISIBLE);

        fftAveraging = (MyEditText) activity.findViewById(R.id.fftAvgEt);
        systemGain = (MyEditText) activity.findViewById(R.id.gainET);

        //=============设置频谱===================================
//        spectrumView3.Connect(this, Outputs.rmsSpectrum3, Outputs.leqSpectrum3, noSpectralLines3, 2000, 8000);
        spectrumView3.Connect(this, null, Outputs.rmsSpectrum3, noSpectralLines3, 2000, 8000);
        spectrumView1.Connect(this, null, Outputs.rmsSpectrum1, noSpectralLines1, 2000, 8000);
//        spectrumView1.Connect(this, Outputs.rmsSpectrum1, Outputs.leqSpectrum1, noSpectralLines1, 2000, 8000);
        fftSpectrumView.Connect(this, null, Outputs.fftSpectrum, noFftSpectralLines, 1000, 8000);

        Keyboard_Listener klFft = new Keyboard_Listener();
        fftAveraging.setOnMyEditTextListener(klFft);

        Keyboard_Listener klSysGain = new Keyboard_Listener();
        systemGain.setOnMyEditTextListener(klSysGain);

        yAxis3.addListener(spectrumView3);
        yAxis1.addListener(spectrumView1);
        yAxisFft.addListener(fftSpectrumView);

    }


    //网线连接
    private class Connect implements Runnable {

        public Connect() {
        }

        public void run() {
            while (running) {
                short[] buffer = null;
                try {
                    buffer = queue.take();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
                int count = 0;
                if (buffer != null) {
                    lock.lock();
                    //30 * 3 = 90
                    for (int i = 0; i < noSpectralLines3; i++) {
                        Outputs.rmsSpectrum3[i] = buffer[count];
                        count++;
                        Inputs.maxSpectrum3[i] = buffer[count];
                        count++;
                    }

                    for (int i = 0; i < noSpectralLines3; i++) {
                        Inputs.leqSpectrum3[i] = buffer[count];
                        count++;
                    }
                    //10 * 3 = 30
                    for (int i = 0; i < noSpectralLines1; i++) {
                        Outputs.rmsSpectrum1[i] = buffer[count];
                        count++;
                        Inputs.maxSpectrum1[i] = buffer[count];
                        count++;
                    }

                    for (int i = 0; i < noSpectralLines1; i++) {
                        Inputs.leqSpectrum1[i] = buffer[count];
                        count++;
                    }

                    Outputs.rms = buffer[count];
                    count++;
                    Inputs.max = buffer[count];
                    count++;
                    Outputs.ln1 = buffer[count];
                    count++;
                    Outputs.ln2 = buffer[count];
                    count++;
                    Outputs.ln3 = buffer[count];
                    count++;
                    Inputs.leq = buffer[count];
                    count++;
                    Inputs.peak = buffer[count];
                    count++;

                    //==127
                    for (int i = 0; i < noFftSpectralLines; i++) {
                        Outputs.fftSpectrum[i] = buffer[count];
                        count++;
                    }
                    if (HunXiangActivity.getMqttClient() != null) {
                        try {
                            short[] bufferData = Arrays.copyOf(buffer, count);
                            String msgHead = "data";
                            byte[] byteValue = new byte[bufferData.length * 2 + 4];

                            System.arraycopy(IpBytes, 0, byteValue, 0, 4);
                            for (int i = 0; i < bufferData.length ; i++) {
                                byteValue[i * 2 + 4] = (byte) (bufferData[i] & 0xff);
                                byteValue[i * 2 + 1 + 4] = (byte) ((bufferData[i] & 0xff00) >> 8);
                            }
                            if (HunXiangActivity.getMqttClient() == null || !HunXiangActivity.getMqttClient().isConnected()){

                            }else {
                                HunXiangActivity.getMqttClient().publish("setApp", byteValue, 1, false);
                            }


                        } catch (MqttException e) {
                            e.printStackTrace();
                        }
                    }


                    functionBlock.Compute();

                    //					long[] t = machine.Timing();
                    //					Log.v("Jens", String.valueOf(t[2]));

                    lock.unlock();

                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            Log.v("jens", "Connect Not Running");
        }
    }
}

